package com.jinsp.networklibrary.util;

import android.annotation.SuppressLint;
import android.util.Log;

import java.nio.charset.Charset;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;

/**
 * Created by luoshuai on 1/15/22
 * <p>
 * AES算法加解密数据，配合BASE64使用
 */
public class AESUtils {

    private static Charset codeCharset;     //编码
    private static final String CIPHER_ALGORITHM_AES = "AES";
    private static Cipher encryptCipher;        //加密
    private static Cipher decryptCipher;        //解密

    @SuppressLint("GetInstance")
    public static void init(String password, String codeFormat) {
        if (codeFormat == null || codeFormat.length() == 0) {
            codeFormat = "utf-8";
        }
        codeCharset = Charset.forName(codeFormat);
        //初始化cipher
        try {
            KeyGenerator.getInstance(CIPHER_ALGORITHM_AES).init(128);
            SecretKeySpec secretKeySpec = new SecretKeySpec(password.getBytes(codeFormat),
                    CIPHER_ALGORITHM_AES);
            String transformation = "AES/ECB/PKCS5Padding";
            encryptCipher = Cipher.getInstance(transformation);
            encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            decryptCipher = Cipher.getInstance(transformation);
            decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 加密字符串，AES,DES必须配合BASE64使用
     *
     * @param targetString 目标字符串
     * @return 加密后的字符串
     */
    public static String encryptString(String targetString) {
        if (targetString == null || targetString.length() == 0) {
            return null;
        }
        //AES加密字节数组
        try {
            byte[] aesEncryptByteArray = encryptByteArray(targetString.getBytes(codeCharset));
            if (aesEncryptByteArray != null) {
                //使用base64加密数据
                byte[] base64EncryptByteArray = BASE64Utils.encryptByteArray(aesEncryptByteArray);
                if (base64EncryptByteArray != null) {
                    return new String(base64EncryptByteArray, codeCharset);
                }
            }
        } catch (Exception e) {
            Log.e("AESUtils", "加密失败");
            return targetString;
        }
        return null;
    }

    /**
     * 加密字节数组
     *
     * @param targetByteArray 目标字节数组
     * @return 加密后的字节数组
     */
    public static byte[] encryptByteArray(byte[] targetByteArray) {
        if (targetByteArray == null || encryptCipher == null) {
            return null;
        }
        byte[] encryptByteArray = null;
        try {
            encryptByteArray = encryptCipher.doFinal(targetByteArray);
        } catch (BadPaddingException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return encryptByteArray;
    }

    /**
     * 解密字符串,AES,DES必须配合BASE64使用
     *
     * @param targetString 目标字符串
     * @return 解密后的字符串
     */
    public static String decryptString(String targetString) {
        if (targetString == null || targetString.length() == 0) {
            return null;
        }
        //base64解密
        try {
            byte[] base64DecryptByteArray = BASE64Utils.decryptByteArray(targetString.getBytes(codeCharset));
            if (base64DecryptByteArray != null) {
                //AES解密
                byte[] aesDecryptByteArray = decryptByteArray(base64DecryptByteArray);
                if (aesDecryptByteArray != null) {
                    return new String(aesDecryptByteArray, codeCharset);
                }
            }
        } catch (Exception e) {
            Log.e("AESUtils", "解密失败");
            return targetString;
        }
        return null;
    }

    /**
     * 解密字节数组
     *
     * @param targetByteArray 目标字节数组
     * @return 解密后的字节数组
     */
    public static byte[] decryptByteArray(byte[] targetByteArray) {
        if (targetByteArray == null || decryptCipher == null) {
            return null;
        }
        byte[] decryptByteArray = null;
        try {
            decryptByteArray = decryptCipher.doFinal(targetByteArray);
        } catch (BadPaddingException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return decryptByteArray;
    }
}
